/*
 * This file is part of the Android Dimensions Editor Project: http://code.google.com/p/android-dimension-editor/
 *  
 * Copyright (c) 2013 Rick Falck
 *  
 * This code is licensed under the terms of the Apache License Version 2.0.
 * You may use this code according to the license.
 *
 * The terms of the license can be found in the root directory of this project's repository as well as at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under these Licenses is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See each License for the specific language governing permissions and
 * limitations under that License.
 */

package ContextMenuButton;

import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Button;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SeparatorMenuItem;
import javafx.scene.effect.Glow;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import model.ItemName;

/**
 * <b><i>public class ContextMenuButton extends Button</i></b>
 * <p>
 * This class manages the button that gets displayed for each dimension item.
 * Initially, it displays the default button that has no function.  The user
 * must right-click the button to select a function to perform on the item.  Then the button gets changed
 * to that function, with a unique icon for it. 
 * The user can then left-click the button to repeat the function or right-click to
 * select another one.
 * 
 * @author Rick Falck
 */
public class ContextMenuButton extends Button {

    private Callback mCB;
    private ItemName mMyItem;
    private ImageView mButtonIcon;
    private ContextMenu mContextMenu;
    private MenuItem mItem_Delete;
    private MenuItem mItem_Insert_Above;
    private MenuItem mItem_Insert_Below;
    private MenuItem mItem_Insert_Comment;
    private MenuItem mItem_Move_Down;
    private MenuItem mItem_Move_Up;
    private MENU_ITEM mCurrentMenuItem = null;

    /**
     * <b><i>public interface Callback</i></b>
     * <p> 
     * This interface meust be implemented to receive notifications of what
     * function the user has selected.
     */
    public interface Callback {
        void onMenuItemSelected(MENU_ITEM menuItem, ItemName selectedItem);
    }

    public ContextMenuButton(Callback cb, ItemName iName) {
        mMyItem = iName;
        mCB = cb;
        mCurrentMenuItem = MENU_ITEM.DEFAULT;
        //this.setId("mItemButton");
        this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
        this.setMaxSize(26, 26);
        this.setMinSize(26, 26);
        mButtonIcon = new ImageView(MENU_ITEM.DEFAULT.getImageUrl());
        mButtonIcon.setFitHeight(26);
        mButtonIcon.setFitWidth(26);
        this.setGraphic(mButtonIcon);

        mContextMenu = new ContextMenu();
        mItem_Delete = new MenuItem(MENU_ITEM.DELETE.getItemText());
        mItem_Insert_Above = new MenuItem(MENU_ITEM.INSERT_ABOVE.getItemText());
        mItem_Insert_Below = new MenuItem(MENU_ITEM.INSERT_BELOW.getItemText());
        mItem_Insert_Comment = new MenuItem(MENU_ITEM.INSERT_COMMENT.getItemText());
        mItem_Move_Up = new MenuItem(MENU_ITEM.MOVE_UP.getItemText());
        mItem_Move_Down = new MenuItem(MENU_ITEM.MOVE_DOWN.getItemText());

        this.addEventHandler(MouseEvent.ANY, new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent e) {
                if (e.getEventType() == MouseEvent.MOUSE_CLICKED) {
                    if (e.getButton() == MouseButton.SECONDARY) {
                        mContextMenu.show(ContextMenuButton.this, e.getScreenX(), e.getScreenY());
                    } else if (e.getButton() == MouseButton.PRIMARY && mCurrentMenuItem != MENU_ITEM.DEFAULT) {
                        mCB.onMenuItemSelected(mCurrentMenuItem, mMyItem);
                    }
                } else if (e.getEventType() == MouseEvent.MOUSE_ENTERED) {
                    setEffect(new Glow(0.9));
                } else if (e.getEventType() == MouseEvent.MOUSE_EXITED) {
                    setEffect(null);
                }
            }
        });

        mItem_Delete.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                handleItemClick(MENU_ITEM.DELETE);
            }
        });

        mItem_Insert_Above.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                handleItemClick(MENU_ITEM.INSERT_ABOVE);
            }
        });

        mItem_Insert_Below.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                handleItemClick(MENU_ITEM.INSERT_BELOW);
            }
        });

        mItem_Insert_Comment.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                handleItemClick(MENU_ITEM.INSERT_COMMENT);
            }
        });

        mItem_Move_Down.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                handleItemClick(MENU_ITEM.MOVE_DOWN);
            }
        });

        mItem_Move_Up.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                handleItemClick(MENU_ITEM.MOVE_UP);
            }
        });

        mContextMenu.getItems().add(mItem_Move_Up);
        mContextMenu.getItems().add(mItem_Move_Down);
        mContextMenu.getItems().add(new SeparatorMenuItem());
        mContextMenu.getItems().add(mItem_Insert_Above);
        mContextMenu.getItems().add(mItem_Insert_Below);
        mContextMenu.getItems().add(mItem_Insert_Comment);
        mContextMenu.getItems().add(new SeparatorMenuItem());
        mContextMenu.getItems().add(mItem_Delete);
    }

    protected void handleItemClick(MENU_ITEM itemClicked) {
        // Set the Icon to the current selection, if it has changed and is not DELETE
        if (mCurrentMenuItem != itemClicked) {
            if (itemClicked.getImageUrl() != null) {
                mButtonIcon = new ImageView(itemClicked.getImageUrl());
                mButtonIcon.setFitHeight(26);
                mButtonIcon.setFitWidth(26);
                this.setGraphic(mButtonIcon);
            }
        }
        mCurrentMenuItem = itemClicked;
        mCB.onMenuItemSelected(mCurrentMenuItem, mMyItem);

    }

    public ItemName getMyItem() {
        return mMyItem;
    }

    public void setMyItem(ItemName myItem) {
        mMyItem = myItem;
    }

    /**
     * <b><i>public enum MENU_ITEM</i></b>
     * <p>
     * This enum is used by the containing class to set the icon
     * for the button, the text to display in the context menu,
     * and to indicate the function selected to the implementing class.
     * <p>
     * The implementing class will use it to determine what function
     * was selected by the user.
     * 
     */
    public enum MENU_ITEM {  

        DEFAULT("/edit_item.png", " "),
        DELETE(null, "Delete"),
        INSERT_ABOVE("/insert_item_above.png", "Insert Item Above"),
        INSERT_BELOW("/insert_item_below.png", "Insert Item Below"),
        INSERT_COMMENT("/insert_comment.png", "Insert Comment Above"),
        MOVE_UP("/arrow_up.png", "Move Up"),
        MOVE_DOWN("/arrow_down.png", "Move Down");

        private String mImageUrl;
        private String mItemText;

        private MENU_ITEM(String imageUrl, String itemText) {
            mImageUrl = imageUrl;
            mItemText = itemText;
        }

        public String getImageUrl() {
            return mImageUrl;
        }

        public String getItemText() {
            return mItemText;
        }
    }

}
